package gnss

import (
	"math"
	"time"
)

/* convert calendar day/time to time -------------------------------------------
* convert calendar day/time to gtime_t struct
* args   : double *ep       I   day/time {year,month,day,hour,min,sec}
* return : gtime_t struct
* notes  : proper in 1970-2037 or 1970-2099 (64bit time_t)
*-----------------------------------------------------------------------------*/

//extern gtime_t epoch2time(const double *ep)
//{
//const int doy[]={1,32,60,91,121,152,182,213,244,274,305,335};
//gtime_t time={0};
//int days,sec,year=(int)ep[0],mon=(int)ep[1],day=(int)ep[2];
//
//if (year<1970||2099<year||mon<1||12<mon) return time;
//
///* leap year if year%4==0 in 1901-2099 */
//days=(year-1970)*365+(year-1969)/4+doy[mon-1]+day-2+(year%4==0&&mon>=3?1:0);
//sec=(int)floor(ep[5]);
//time.time=(time_t)days*86400+(int)ep[3]*3600+(int)ep[4]*60+sec;
//time.sec=ep[5]-sec;
//return time;
//}

// 根据当前时间进行转换
// 如果转换历史数据可能存在问题
// 周数获取当前时间的utc时间
// tow为周内毫秒
func TOW2Time(refutcTime time.Time, tow uint) time.Time {
	utcNow := refutcTime

	if utcNow.IsZero() {
		utcNow = time.Now().UTC()
	} else {
		utcNow = utcNow.UTC()
	}

	_, tow_p := Time2GpsT(utcNow)
	tow_p = tow_p * 1000
	if float64(tow) < tow_p-302400000.0 { // 当前时间-半周
		tow += 604800000
	} else if float64(tow) > tow_p+302400000.0 { // 当前时间+半周
		tow -= 604800000
	}

	d := time.Hour * 24 * time.Duration(utcNow.Weekday()) * -1
	startOfWeek := utcNow.Add(d) // this week first day
	startOfWeek = time.Date(startOfWeek.Year(), startOfWeek.Month(), startOfWeek.Day(), 0, 0, 0, 0, time.UTC)
	rval := startOfWeek.Add(time.Duration(tow) * time.Millisecond)
	return rval
}

/*
*

	week: gpsweek
	tow: Milliseconds from beginning of the week
*/
func TOW2TimeEx(week, tow uint) time.Time {
	startOfWeek := GPS_START_TIME.Add(time.Hour * 24 * 7 * time.Duration(week))
	startOfWeek = time.Date(startOfWeek.Year(), startOfWeek.Month(), startOfWeek.Day(), 0, 0, 0, 0, time.UTC)
	rval := startOfWeek.Add(time.Duration(tow) * time.Millisecond)
	return rval
}

/*
*
 */
func MJDSOD2Time(mjd, sod int) time.Time {
	startOfDay := MJD2Time(mjd)
	rval := startOfDay.Add(time.Duration(sod) * time.Second)
	return rval
}

/*
*
int md_julday(int iyear, int imonth, int iday)

	{
	 int iyr, result;
	 int doy_of_month[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
	 if (iyear < 0 || imonth < 0 || iday < 0 || imonth > 12 || iday > 366 || (imonth != 0 && iday > 31))
	 {
	   return 0;
	 }
	 iyr = iyear;
	 if (imonth <= 2) iyr -= 1;

	 result = 365 * iyear - 678941 + iyr / 4 - iyr / 100 + iyr / 400 + iday;
	 if (imonth != 0) result = result + doy_of_month[imonth - 1];
	 return result;
	}

日期转mjd
*/
func Date2MJD(year, month, day int) int {
	var doy_of_month = [12]int{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}

	iyr := year
	if month <= 2 {
		iyr -= 1
	}
	r := 365*year - 678941 + iyr/4 - iyr/100 + iyr/400 + day
	if month != 0 {
		r += doy_of_month[month-1]
	}
	return r
}

/*
*
void mjd2doy(int jd, int *iyear, int *idoy)

	{
		*iyear = (jd + 678940) / 365;
		printf("iyear %d\n", *iyear);
		int mjd=md_julday(*iyear, 1, 1);
		printf("mjd %d\n", mjd);
		*idoy = jd - mjd;
		printf("idoy %d\n", *idoy);
		while (*idoy <= 0)
		{
		(*iyear)--;
		*idoy = jd - md_julday(*iyear, 1, 1) + 1;
		}
	}

mjd 转成日期
*/
func MJD2Time(mjd int) time.Time {
	year := (mjd + 678940) / 365
	day := mjd - Date2MJD(year, 1, 1)
	for day <= 0 {
		year--
		day = mjd - Date2MJD(year, 1, 1) + 1
	}
	rval := time.Date(year, 1, 1, 0, 0, 0, 0, time.UTC)
	if day > 1 {
		rval = rval.Add(time.Hour * 24 * time.Duration(day-1))
	}
	return rval
}

func GloTOD2Time(refutcTime time.Time, TOD int64) time.Time {
	utcNow := refutcTime
	t := GPSTime2UTC(utcNow).Add(10800 * time.Second) // GLONASS 历元时间是 GLONASS ICD 定义的系统时间为 UTC（SU）+3.0hours.
	week, tow := ToGPSTime(t)                         // 返回周内秒， 周
	_, re := math.Modf(float64(tow) / float64(86400)) // 求 1天之内的秒数
	tod_p := float64(re * 86400)                      // tod_p: second of day
	tow -= tod_p                                      // 当前的周内秒 - 天内秒

	tod := float64(TOD) * 0.001         // （天内秒） 毫秒 -> 秒
	if tod < (float64(tod_p) - 43200) { //43200 为 12小时
		tod += 86400 // + 一天
	} else if tod > (float64(tod_p) + 43200) {
		tod -= 86400 // + 一天
	}

	rtime := WeekSOWToTime(week, tow+tod).Add(-10800 * time.Second)
	rtime = UTC2GPSTime(rtime)
	return rtime
}

//func Glo2Time(refutcTime time.Time, dow byte, sod uint32) time.Time {
//	utcNow := refutcTime
//	t := GPSTime2UTC(utcNow).Add(10800 * time.Second) // GLONASS 历元时间是 GLONASS ICD 定义的系统时间为 UTC（SU）+3.0hours.
//	week, tow := ToGPSTime(t)                         // 返回周内秒， 周
//	_, re := math.Modf(float64(tow) / float64(86400)) // 求 1天之内的秒数
//	tod_p := float64(re * 86400)                      // tod_p: second of day
//	tow -= tod_p                                      // 当前的周内秒 - 天内秒
//
//	tod := float64(sod) * 0.001         // （天内秒） 毫秒 -> 秒
//	if tod < (float64(tod_p) - 43200) { //43200 为 12小时
//		tod += 86400 // + 一天
//	} else if tod > (float64(tod_p) + 43200) {
//		tod -= 86400 // + 一天
//	}
//
//	rtime := GPSToUtcTime(dow, tow+tod).Add(-10800 * time.Second)
//	rtime = UTC2GPSTime(rtime)
//	return rtime
//}
